"""Logic of exploration, middleware for django models"""

import fca
from fca.algorithms.exploration.exploration import (AttributeExploration, 
                                                    ExplorationDB)

from models import Object, Attribute, AttributeImplication, ObjectImplication

class Expert(object):
    """docstring for Expert"""
    def __init__(self, name="", intent=None):
        super(Expert, self).__init__()
        self.name = name
        self.intent = intent
    
    def learn_counterexample(self, name, intent):
        self.name = name
        self.intent = intent    
    
    def provide_counterexample(self, imp):
        return (self.name, self.intent)
        

class ModeledExplorationDB(ExplorationDB):
    """docstring for ModeledExplorationDB"""
    def __init__(self):
        
        def get_context_as_cxt():
            all_objects = Object.objects.all()
            all_attributes = Attribute.objects.all()
            object_names = [obj.name for obj in all_objects]
            attribute_names = [attr.name for attr in all_attributes]
            table = []
            for obj in all_objects:
                table.append(obj.get_as_boolean_list())
            return fca.Context(table, object_names, attribute_names)
        
        def get_confirmed_implications():
            ans = []
            confirmed_attr_implications = \
                AttributeImplication.objects.filter(is_confirmed=True)
            for imp in confirmed_attr_implications:
                ans.append(imp.get_fca_implication())
            return ans
        
        cxt = get_context_as_cxt()
        confirmed_implications = get_confirmed_implications()
        super(ModeledExplorationDB, self).__init__(cxt, 
                                                   confirmed_implications)
                                                   
    def confirm_implication(self, imp):
        fca_imp = imp.get_fca_implication()
        super(ModeledExplorationDB, self).confirm_implication(fca_imp)
        imp.is_confirmed = True
        imp.save()
        
    def unconfirm_implication(self, imp):
        fca_imp = imp.get_fca_implication()
        super(ModeledExplorationDB, self).unconfirm_implication(fca_imp)
        imp.is_confirmed = False
        imp.save()
        
    def add_example(self, name, intent):
        super(ModeledExplorationDB, self).add_example(name, intent)
        new_object = Object(name=name)
        new_object.save()
        for attr in intent:
            attr_object = Attribute.objects.get(name=attr)
            new_object.attributes.add(attr_object)
        self.sync_implications()
        
    def delete_example(self, name):
        super(ModeledExplorationDB, self).delete_example(name)
        self.sync_implications()
        
    def delete_attribute(self, name):
        super(ModeledExplorationDB, self).delete_attribute(name)
        self.sync_implications()
        
    def check_form_and_add_example(self, form, name, intent):
        super(ModeledExplorationDB, self).add_example(name, intent)
        form.save()
        self.sync_implications()
        
    def check_form_and_edit_example(self, form, name, old_name, intent):
        super(ModeledExplorationDB, self).edit_example(name, old_name, intent)
        form.save()
        self.sync_implications()
        
    def check_form_and_add_attribute(self, form, name, extent):
        super(ModeledExplorationDB, self).add_attribute(name, extent)
        form.save()
        self.sync_implications()
        
    def check_form_and_edit_attribute(self, form, name, old_name, extent):
        super(ModeledExplorationDB, self).edit_attribute(name, old_name, extent)
        form.save()
        self.sync_implications()   
        
    def sync_implications(self):
        AttributeImplication.objects.filter(is_confirmed=False).delete()
        for imp in self.open_implications:
            AttributeImplication.create_from_fca_implication(imp)
       
db = ModeledExplorationDB()
expert = Expert()
exploration = AttributeExploration(db, expert)

def reload():
    global db
    global expert
    global exploration
    db = ModeledExplorationDB()
    expert = Expert()
    exploration = AttributeExploration(db, expert)